package cuongnh.project.japanesediary.vocabulary.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import cuongnh.project.japanesediary.vocabulary.model.Category;
import cuongnh.project.japanesediary.vocabulary.model.Grammar;
import cuongnh.project.japanesediary.vocabulary.model.Kanji;
import cuongnh.project.japanesediary.vocabulary.model.Sentence;
import cuongnh.project.japanesediary.vocabulary.model.Vocabulary;

@Repository
@Transactional
public class CategoryDao extends HibernateDaoSupport {

	public void save(Category a1) {
		a1.setCreatedDate(new Date());
		a1.setModifiedDate(new Date());
		getHibernateTemplate().save(a1);
	}
	
	public void saveOrUpdate(Category a1) {
		a1.setModifiedDate(new Date());
		if(a1.getCreatedDate() == null){
			a1.setCreatedDate(new Date());
		}
		getHibernateTemplate().saveOrUpdate(a1);
	}

	/**
	 * 'load' returns a proxy with only the id populated. To access members in
	 * the proxy requires a Hibernate session. Haven't figured out how to do
	 * transactions between bundles yet...
	 */
	public Category load(long id) {
		return (Category) getHibernateTemplate().load(Category.class, id);
	}

	public Category get(long id) {
		return (Category) getHibernateTemplate().get(Category.class, id);
	}

	public void update(Category a1) {
		a1.setModifiedDate(new Date());
		getHibernateTemplate().update(a1);
	}

	/**
	 * Delete current category with all association function
	 * 
	 * @param a1
	 *            : Current category
	 */
	public void delete(Category a1) {
		getHibernateTemplate().delete(a1);
	}

	public Category merge(Category a1) {
		a1.setModifiedDate(new Date());
		return (Category) getHibernateTemplate().merge(a1);
	}

	public List<Category> getAll() {
		List<Category> result = new ArrayList<Category>();
		result = getHibernateTemplate().loadAll(Category.class);
		if(result == null || result.isEmpty()){
			return new ArrayList<Category>();
		}
		
		return result;
	}

	public Set<Category> getAllParentWithSubCategories() {
		Set<Category> result = new HashSet<Category>();
		List<Category> all = getAll();
		if(all != null && !all.isEmpty()){
			for (Category category : all) {
				if (category.getParentCategory() == null) {
					initAllSubCategories(category);
					result.add(category);
				}
			}
		}

		return result;
	}

	private void initAllSubCategories(Category category) {
		getHibernateTemplate().initialize(category.getSubCategories());
		for (Category cat : category.getSubCategories()) {
			initAllSubCategories(cat);
		}
	}
	
	public Category getCategoryWithSubCategories(long categoryId) {
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		getHibernateTemplate().initialize(category.getSubCategories());
		return category;
	}

	public Category getCategoryWithVocabularies(long categoryId) {
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		getHibernateTemplate().initialize(category.getVocabularies());
		return category;
	}
	
	public Set<Vocabulary> getCategoryVocabularies(long categoryId) {
		Set<Vocabulary> result = new HashSet<Vocabulary>();
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		if(category != null){
			getHibernateTemplate().initialize(category.getVocabularies());
			result = category.getVocabularies();
		}
		
		return result;
	}
	
	public Set<Kanji> getCategoryKanjis(long categoryId) {
		Set<Kanji> result = new HashSet<Kanji>();
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		if(category != null){
			getHibernateTemplate().initialize(category.getKanjis());
			result = category.getKanjis();
		}
		
		return result;
	}
	
	public Set<Grammar> getCategoryGrammars(long categoryId) {
		Set<Grammar> result = new HashSet<Grammar>();
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		if(category != null){
			getHibernateTemplate().initialize(category.getGrammars());
			result = category.getGrammars();
		}
		
		return result;
	}
	
	public Set<Sentence> getCategorySentences(long categoryId) {
		Set<Sentence> result = new HashSet<Sentence>();
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		if(category != null){
			getHibernateTemplate().initialize(category.getSentences());
			result = category.getSentences();
		}
		
		return result;
	}
	
	public Category getCategoryWithGrammars(long categoryId) {
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		getHibernateTemplate().initialize(category.getGrammars());
		return category;
	}
	
	public Category getCategoryWithKanjis(long categoryId) {
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		getHibernateTemplate().initialize(category.getKanjis());
		return category;
	}
	
	public Category getCategoryWithSentences(long categoryId) {
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		getHibernateTemplate().initialize(category.getSentences());
		return category;
	}

	public Category getCategoryWithAllLazies(long categoryId) {
		Category category = getHibernateTemplate().get(Category.class,
				categoryId);
		getHibernateTemplate().initialize(category.getSubCategories());
		getHibernateTemplate().initialize(category.getVocabularies());
		getHibernateTemplate().initialize(category.getGrammars());
		getHibernateTemplate().initialize(category.getKanjis());
		getHibernateTemplate().initialize(category.getSentences());
		return category;
	}

}